#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>

#include "kylin-activation.h"

/*
 * transform_valid_char, check if ch is a valid character
 * return true if valid, or return false
 */
static bool transform_valid_char(char ch)
{
    if(('a' <= ch && ch <= 'z') ||
       ('A' <= ch && ch <= 'Z') ||
       ('0' <= ch && ch <= '9') ||
       (ch == '+') ||
       (ch == '/') ||
       (ch == '=') ||
       (ch == '%'))
    {
        return true;
    } else {
        return false;
    }

    return false;
}

/*
 * transform_validate, check if url is a valid transform string
 * return NO_ERROR if it is valid, or return error number
 */
static int transform_validate(const char* url)
{
    unsigned int i = 0;
    size_t len = 0;

    len = strlen(url);
    for(i = 0; i < len; i++)
    {
        if(!transform_valid_char(url[i]))
        {
            return TRANSFORM_CHAR_ERROR;
        }
    }

    return NO_ERROR;
}

/*
 * transform_from_url, transform from url string
 * return NO_ERROR if succeeds, or return error number
 */
int transform_from_url(const char* url, unsigned int in_size, char* out, unsigned int *out_size)
{
    unsigned int i, j;
    int ret;

    if(!url || !out || !out_size || (in_size == 0))
        return TRANSFORM_FROM_URL_ERROR;

    *out_size = 0;

    ret = transform_validate(url);
    if(ret != NO_ERROR)
        return ret;

    for(i = 0, j = 0; i < in_size; i++, j++)
    {
        if(url[i] == '%')
        {
            if(strncmp(url + i, "%2B", 3) == 0)
            {
                out[j] = '+';
            } else if(strncmp(url + i, "%2F", 3) == 0) {
                out[j] = '/';
            } else if(strncmp(url + i, "%3D", 3) == 0) {
                out[j] = '=';
            } else {
                return TRANSFORM_PARSE_ERROR;
            }
            i += 2;
        } else {
            out[j] = url[i];
        }
    }
    out[j] = '\0';

    *out_size = j;

    return NO_ERROR;
}

/*
 * transform_to_url, transform string tofrom url
 * return NO_ERROR if succeeds, or return error number
 */
int transform_to_url(const char* in, unsigned int in_size, char* out, unsigned int *out_size)
{
    unsigned int i, j;
    int ret;

    if(!in || !out || !out_size || (in_size == 0))
        return TRANSFORM_TO_URL_ERROR;

    *out_size = 0;

    ret = transform_validate(in);
    if(ret != NO_ERROR)
        return ret;

    for(i = 0, j = 0; i < in_size; i++, j++)
    {
        if(in[i] == '+')
        {
            out[j] = '%';
            out[j + 1] = '2';
            out[j + 2] = 'B';
            j += 2;
        } else if(in[i] == '/') {
            out[j] = '%';
            out[j + 1] = '2';
            out[j + 2] = 'F';
            j += 2;
        } else if(in[i] == '=') {
            out[j] = '%';
            out[j + 1] = '3';
            out[j + 2] = 'D';
            j += 2;
        } else {
            out[j] = in[i];
        }
    }

    out[j] = '\0';
    *out_size = j;

    return NO_ERROR;
}
